/*
 * ==================================================================
 * Pardal - Framework for Classification Hierarchical and Multilabel.
 * ==================================================================
 * 
 * Copyright (C) 2013-2014 
 *  Valdigleis da Silva Costa
 *  Araken Medeiros Santos
 *  Daniel Sabino Amorim de Araujo
 *
 *  Departamento de Ciências Exatas, Tecnologicas e Humanas (DCETH) 
 *  Grupo de Inteligência Computacionais de Angicos (GICA)
 *  Campus Angicos (CA)
 *  Universidade Federal Rural do Semi-árido (UFERSA)
 *
 *  Project Info: (Site em desenvolvimento)
 * 
 * Framework Pardal is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * Framework Pardal is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 * 
 * ==================================================================
 * Pardal - Framework para Classificação Hierárquica e Multirrótulo.
 * ==================================================================
 * 
 * Copyright (C) 2013-2014 
 *  Valdigleis da Silva Costa
 *  Araken Medeiros Santos
 *  Daniel Sabino Amorim de Araujo
 *
 *  Departamento de Ciências Exatas, Tecnologicas e Humanas (DCETH) 
 *  Grupo de Inteligência Computacionais de Angicos (GICA)
 *  Campus Angicos (CA)
 *  Universidade Federal Rural do Semi-árido (UFERSA)
 *
 * Informações sobre o projeto: (Site em Desenvolvimento)
 * 
 * O Framework Pardal é um software livre; você pode redistribui-lo e/ou
 * modifica-lo dentro dos termos da Licença Pública Geral GNU como 
 * publicada pela Fundação do Software Livre (FSF); na versão 2 da 
 * Licença, ou (na sua opnião) qualquer versão.
 * 
 * O Framework Pardal é distribuido na esperança que possa ser util, 
 * mas SEM NENHUMA GARANTIA; sem uma garantia implicita de ADEQUAÇÂO
 * a qualquer MERCADO ou APLICAÇÃO EM PARTICULAR. Veja a
 * Licença Pública Geral GNU para maiores detalhes.
 * 
 * Você deve ter recebido uma cópia da Licença Pública Geral GNU
 * junto com este programa, se não, escreva para a Fundação do Software
 * Livre(FSF) Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

package pardal.gica.gui.config.ensembles;


import java.text.ParseException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.text.MaskFormatter;
import pardal.gica.gui.HierarquicSelection;
import pardal.gica.gui.results.TextResult;
import pardal.classifiers.HMLP;
import weka.classifiers.Classifier;
import weka.classifiers.meta.Bagging;
import weka.core.Instances;

/**
 *
 * @author Valdigleis
 */
public class ConfigBagging extends JDialog {
    
    //Frame pai
    private HierarquicSelection father;
    //Classificador base
    private  Classifier     classifierBase;
    //Int para porcetagem de bag de treinamento
    private  int         bag;
    //Número de interações
    private  int            interaation;
    //Jlabel para o classificador
    private  JLabel         textClassifiers;
    //Jtextfield para o classificador
    private  JTextField     nameClassifiers;
    //JButton para o classificador.
    private  JButton        selection;
    //Algoritmo Bagging
    private  Bagging        bagging;
    //Opção de execução
    private  int            option;
    //Instâncias do problemas
    private  Instances      instances;
    //Label para o campo de número componentes do comitê
    private  JLabel         inter;
    //Campo que guarda o valor de interações
    private JFormattedTextField valueInter;
    //Máscara para o campo K
    private MaskFormatter mask; 
    //Campo que guarda o valor de bag
    private JFormattedTextField valueBag;
    //Máscara para o campo K
    private MaskFormatter maskBag;
    //Label para o campo de número de bag do comitê
    private  JLabel         bagLabel;
    //Seletor do tipo de previsão
    private JComboBox seletorOpt;

    public ConfigBagging(HierarquicSelection father, int opt, Instances instances) throws ParseException {
        super(father);
        this.father = father;
        this.option = opt;
        this.instances = instances;
        initComponents();
    }
    
    private void initComponents() throws ParseException{
        
        this.setTitle("bagging");
        this.setSize(450, 250);
        this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        this.setLocationRelativeTo(null);
        this.setLayout(null);
        this.setModal(true);
        this.setResizable(false);
        
        this.textClassifiers = new JLabel("Classificador Base:");
        this.textClassifiers.setBounds(10, 10, 150, 25);
        this.nameClassifiers = new JTextField("Sem Classificador Base definido");
        this.nameClassifiers.setBounds(130, 10, 190, 25);
        this.nameClassifiers.setEditable(false);
        this.nameClassifiers.setToolTipText("Classificador Base selecionado");
        this.selection = new JButton("Selecionar");
        this.selection.setToolTipText("Botão para acionar a seleção de componentes básicos");
        this.selection.setBounds(330, 10, 100, 25);
        this.selection.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                try {
                    configPainel();
                } catch (ParseException ex) {
                    Logger.getLogger(ConfigBagging.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
        
        this.inter = new JLabel("Número de componentes/interações:");
        this.inter.setBounds(10, 40, 220, 25);
        
        this.valueInter = new JFormattedTextField();
        this.valueInter.setToolTipText("Quantidade de componentes no comitês");
        this.valueInter.setBounds(225, 40, 40, 25);
        
        this.mask = new MaskFormatter("#");
        this.mask.setValidCharacters("0123456789");
        this.mask.setCommitsOnValidEdit(true);
        this.mask.install(this.valueInter);
        
        this.bagLabel = new JLabel("Porcetagem nos bag:");
        this.bagLabel.setBounds(10, 70, 220, 25);
        
        this.valueBag = new JFormattedTextField();
        this.valueBag.setToolTipText("Porcetagem de exemplo usados");
        this.valueBag.setBounds(225, 70, 40, 25);
        this.valueBag.setText("00");
        
        this.maskBag = new MaskFormatter("##");
        this.maskBag.setValidCharacters("0123456789");
        this.maskBag.setCommitsOnValidEdit(true);
        this.maskBag.install(this.valueBag);
        
        JLabel seletor = new JLabel("Previsão nas folhas");
        seletor.setBounds(10, 100, 150, 25);
        
        this.seletorOpt = new JComboBox();
        this.seletorOpt.addItem("Não");
        this.seletorOpt.addItem("Sim");
        this.seletorOpt.setBounds(160, 100, 150, 25);
        
        JButton ok = new JButton("OK");
        ok.setToolTipText("Porcetagem de exemplo usados");
        ok.setBounds(120, 170, 90, 25);
        ok.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                try {
                    if(testFields()){
                        runBagging();
                    }
                } catch (Exception ex) {
                    Logger.getLogger(ConfigBagging.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
                }
            }
        });
        
        JButton cancel = new JButton("Cancel");
        cancel.setToolTipText("Porcetagem de exemplo usados");
        cancel.setBounds(220, 170, 90, 25);
        cancel.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                dispose();
            }
        });

        
        this.add(this.textClassifiers);
        this.add(this.nameClassifiers);
        this.add(this.selection);
        this.add(this.inter);
        this.add(this.valueInter);
        this.add(this.bagLabel);
        this.add(this.valueBag);
        this.add(seletor);
        this.add(this.seletorOpt);
        this.add(ok);
        this.add(cancel);
        this.setVisible(true);
    }
    
    private boolean check(){
        if(this.nameClassifiers.getText().trim().equals("Sem Classificador Base definido")){
            return true;
        }else{
            return false;
        }
    }
    
    private void configPainel() throws ParseException{
        if(check()){
            PanielClassiferBase pn = new PanielClassiferBase(this);
            int opt = pn.getoption();
            pn.dispose();
            switch (opt){
                case 1:
                    ConfigKnn knn = new ConfigKnn(father);
                    this.classifierBase = knn.getKNN();
                    knn.dispose();
                    this.nameClassifiers.setText("KNN");
                    break;
                case 2:
                    ConfigNaive naive = new ConfigNaive(father, instances);
                    this.classifierBase = naive.getNaive();
                    naive.dispose();
                    this.nameClassifiers.setText("Naive Bayse");
                    break;
                case 3:
                    ConfigRNA rna = new ConfigRNA(this.father);
                    this.classifierBase = rna.getRNA();
                    rna.dispose();
                    this.nameClassifiers.setText("Perceptron");
                    break;
                case 4:
                    ConfigJ48 tree = new ConfigJ48(this.father, instances, this.option);
                    this.classifierBase = tree.getTree();
                    tree.dispose();
                    this.nameClassifiers.setText("Decision Tree");
                    break;
                default:
                    break;
            }
        }else{
            JOptionPane.showMessageDialog(this.father, "O classificador base atual será alterado!");
            PanielClassiferBase pn = new PanielClassiferBase(this);
            int opt = pn.getoption();
            pn.dispose();
            switch (opt){
                case 1:
                    ConfigKnn knn = new ConfigKnn(father);
                    this.classifierBase = knn.getKNN();
                    knn.dispose();
                    this.nameClassifiers.setText("KNN");
                    break;
                case 2:
                    ConfigNaive naive = new ConfigNaive(father, instances);
                    this.classifierBase = naive.getNaive();
                    naive.dispose();
                    this.nameClassifiers.setText("Naive Bayse");
                    break;
                case 3:
                    ConfigRNA rna = new ConfigRNA(this.father);
                    this.classifierBase = rna.getRNA();
                    rna.dispose();
                    this.nameClassifiers.setText("Perceptron");
                    break;
                case 4:
                    ConfigJ48 tree = new ConfigJ48(this.father, instances, this.option);
                    this.classifierBase = tree.getTree();
                    tree.dispose();
                    this.nameClassifiers.setText("Decision Tree");
                    break;
                default:
                    break;
            }
        }
    }
    
    private boolean testFields(){
        if(this.valueBag.getText().trim().equals(".")){
            JOptionPane.showMessageDialog(this.father, "Preencha o campo de valor do Bag");
            return false;
        }
        if(this.valueInter.getText().trim().equals("")){
            JOptionPane.showMessageDialog(this.father, "O Campo Interações deve ser preeenchido");
            return false;
        }
        this.bag = Integer.parseInt(this.valueBag.getText().trim());
        this.interaation = Integer.parseInt(this.valueInter.getText().trim());
        if(this.bag < 1 || this.interaation < 1){
            JOptionPane.showMessageDialog(this.father, "O número de bag deve ser entre 0 e 99, e as interações < 10");
            return false;
        }
        if(this.nameClassifiers.getText().trim().equals("Classificador Base selecionado")){
            JOptionPane.showMessageDialog(this.father, "Selecione um classificador base para o Bagging!");
            return false;
        }else{
            return true;
        }
    }
    
    private void runBagging() throws Exception{
        if(this.option == 1){
            this.bagging = new Bagging();
            this.bagging.setClassifier(this.classifierBase);
            HMLP hlmp = new HMLP(classifierBase, this.instances, this.seletorOpt.getSelectedIndex());
            hlmp.buildClassifier(instances);
            this.dispose();
        }
    }
    
    public static void main(String[] args) throws ParseException{
        new ConfigBagging(null, 1, null);
    }
}
